package Dungeon;

import java.util.Iterator;

import ConditionPackage.Condition;
import ConditionPackage.DefaultCondition;
import SquarePackage.Direction;
import SquarePackage.Square;
import SquarePackage.TransparentSquare;
import be.kuleuven.cs.som.annotate.Model;

/**
 * Class for a level, a dungeon with only one level.
 * 
 * @invar	All coordinates are positive and smaller than the maximum value.
 * 			| isValidDimension()
 * @invar	The maximum dimension has as Z-value always one. 
 * 			| isValidMaxDimension(maxDimension)
 * 
 * @author 	Brecht Reynders en Florian Hendrickx
 * @version	1.0
 */
public class Level<E extends Square> extends Dungeon<E> {
	
	/**
	 * Initializes a new level with the given coordinates for the maximum and one as the maximum Z-coordinate value.
	 * 
	 * @param 	maxX
	 * 			The maximum x-coordinate value.
	 * @param 	maxY
	 * 			The maximum y-coordinate value.
	 * @effect	The new dungeon is initialized with the given coordinates and 1 as the new maximum z-coordinate value.
	 * 			| super(maxX, maxY, 1)
	 */
	public Level(long maxX, long maxY){
		super(maxX, maxY,0);
	}
	
	/**
	 * Initializes a new dungeon with the given dimension as maximum dimension.
	 * 
	 * @param	maxDimension
	 * 			The new maximum dimension.
	 * @effect	The new dungeon gets initialized with the given coordinates.
	 * 			| super(maxDimension)
	 */
	public Level(Dimension maxDimension){
		super(maxDimension);
	}
	
	/**
	 * Initializes a new level with 20 as the maximum x- and y-coordinate values and one as the maximum Z-coordinate value.
	 * 
	 * @effect	The new dungeon is initialized with 20 as the new maximum x- and y-coordinates and 1 as the new maximum z-coordinate value.
	 * 			| super(20,20, 1)
	 */
	public Level(){
		this(20,20);
	}
	/**
	 * Checks whether the given dimension is a valid new maximum dimension.
	 * 
	 * @param 	maxDimension
	 * 			The new wanted dimension.
	 * @return	True if and only if the dimension is larger than the previous maximum dimension
	 * 			| result = super.isValidNewMaxDimension(maxDimension) && isValidMaxDimension(maxDimension)
	 * @return	True if and only if the z-coordinate value equals.
	 * 			| result = maxDimension.getZposition()==0
	 */
	@Override
	protected boolean isValidNewMaxDimension(Dimension maxDimension){
		return super.isValidNewMaxDimension(maxDimension)&&maxDimension.getZPosition()==0;
	}
	
//	/**
//	 * Add the given square on the given dimension.
//	 * 
//	 * @param 	square
//	 * 			The square to add.
//	 * @param 	dimension
//	 * 			The dimension where the square should be added.
//	 * @post	The square is added at the given dimension.
//	 * 			| getAllSquares().contains(square)
//	 * 			| getAllDimensions().contains(dimension)
//	 * @throws 	IllegalArgumentException
//	 * 			One of the arguments is not a valid argument.
//	 * 			| !isValidDimension()||!isValidSquare()
//	 */
//	@Model @Override
//	public void addSquare(Square square, Dimension dimension){
//	
	/**
	 * @pre this method cannot be used with transparent Squares, because of performace issues and because the wide amount of checks that would  have to be performed
	 * method to set a random amount of squares starting from a certain Square and filling the level with adjointed squares
	 * @param Dimension the dimension to start from
	 * @param the square that functions as model
	 * @param length the amount of squares to set
	 * @post	a level witch contains length more squares.
	 * 			new.getAllSquares.size() = getAllSquares.size()+length
	 */
	public void fillWithRandomAmountOfSquares(Dimension dimension, E baseSquareLevel, int length) {
		assert(baseSquareLevel.getClass()!=TransparentSquare.class);
		int i = 0;
		int errorCounter = 0;
		addSquare(baseSquareLevel, dimension);
		while(i<length-1 && errorCounter < 99 ){
			Dimension oldDimension = new Dimension(dimension.getXPosition(),dimension.getYPosition(),dimension.getZPosition());
			Direction tempDirection = Direction.getRandomDirection();
			if(tempDirection!= Direction.CEILING && tempDirection!= Direction.FLOOR){
			dimension = dimension.getDimensionIn(tempDirection);
			}
			if(!isValidDimension(dimension)){
				errorCounter++;
				dimension = new Dimension(oldDimension.getXPosition(), oldDimension.getYPosition(),oldDimension.getZPosition());
			}
			else{
				E square = (E) baseSquareLevel.clone();
				try{
					addSquare(square, dimension);
				}
				catch(IllegalArgumentException exc){
					System.out.print("You cannot put Rocks next to TransparentSquares\n");
				}
				i++;
				errorCounter = 0;
			}
		}
	}
	/**
	 * method to set a number of squares in one time by given a starting position and extending until the preferred length is reached
	 * @param dimension the starting dimension
	 * @param baseSquareShaft the Square the other squares will resemble
	 * @param length	the amount of Squares to set.
	 * @param increase	true means increasing dimension, false means decreasing
	 * @post the amount of squares in the shaft is incremented by length
	 * 			new.getAllSquares().size() = getAllSquares().size() + length
	 */
	public void fillInDirection(Dimension dimension, E baseSquare, int length, Direction direction) {
		addSquare(baseSquare, dimension);
		int i = 0;
		while(i<length){
			dimension = dimension.getDimensionIn(direction);
			if(!isValidDimension(dimension)){
				i=length;
			}
			else{
				E square = (E) baseSquare.clone();
				addSquare(square, dimension);
				i++;
			}
		}
		}
}
